package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.ExecutorServiceUtil;
import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogParser;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@Qualifier("LogItemWithExecutorCxyImpl")
public class LogItemWithExecutorCxyImpl implements LogParser {
    @Override
    public Map<String, List<LogItem>> parse(String folderName) {
        Map<String, List<LogItem>> resultMap = new ConcurrentHashMap<>();
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
//        ExecutorService executorService = Executors.newFixedThreadPool(60);
        int fileCount = getFileCount(new File(folderName));
        CountDownLatch latch = new CountDownLatch(fileCount);
        processDirectory(new File(folderName), resultMap, executorService, latch);
        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();

        } finally {
            ExecutorServiceUtil.shutdown(executorService);
        }
        return resultMap;
    }

    private int getFileCount(File directory) {
        File[] files = directory.listFiles();
        if (files == null) {
            return 0;
        }
        int count = 0;
        for (File file : files) {
            if (file.isDirectory()) {
                count += getFileCount(file);
            } else if (file.getName().endsWith(".log")) {
                count++;
            }
        }
        return count;
    }

    private void processDirectory(File directory, Map<String, List<LogItem>> resultMap, ExecutorService executorService, CountDownLatch latch) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    processDirectory(file, resultMap, executorService, latch);
                } else if (file.getName().endsWith(".log")) {
                    executorService.submit(() -> processLogFileAndParse(file.getAbsolutePath(), resultMap, latch));
                }
            }
        }
    }

    private void processLogFileAndParse(String filePath, Map<String, List<LogItem>> resultMap, CountDownLatch latch) {
        try {
            List<String> lines = Files.readAllLines(Paths.get(filePath));
            List<LogItem> logItems = new ArrayList<>();

            LogItemParserCxyImpl logItemParser = new LogItemParserCxyImpl();

            for (String line : lines) {
                Optional<LogItem> parsedLogItem = logItemParser.parse(line);
                parsedLogItem.ifPresent(logItems::add);
            }
            resultMap.put(filePath, logItems);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            latch.countDown();
        }
    }
}
